#include "iec61850_server.h"
#include "hal_thread.h"
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <linux/un.h>
#include <sys/time.h>
#include <modbus.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#include "static_model.h"
#include "pcs_modbus_registers.h"
#include "pcs_server.h"

typedef struct {
    int key;
    int value;
    bool valid;
}keyValueMap;

typedef struct {
    int addr;
    int mum;
    keyValueMap *Map;
}regEnumMap;

keyValueMap enum_3505[] = {
    {1, 1, true},
    {2, 2, true}
};

keyValueMap enum_3509[] = {
    {0, 0, true},
    {1, 1, true},
    {2, 2, true}
};

keyValueMap enum_3510[] = {
    {0, 0, true},
    {1, 1, true},
    {2, 2, true},
    {3, 3, true}
};

keyValueMap enum_3513[] = {
    {380, 380, true},
    {400, 400, true},
    {415, 415, true}
};

keyValueMap enum_3515[] = {
    {0, 0, true},
    {1, 1, true},
    {1000, 1000, true}
};

keyValueMap enum_3523[] = {
    {50, 50, true},
    {60, 60, true}
};

keyValueMap enum_3528[] = {
    {0, 1, true},
    {1, 2, true}
};

keyValueMap enum_3534[] = {
    {0, 2, true},
    {1, 1, true}
};

keyValueMap enum_3535[] = {
    {0, 1, true},
    {1, 2, true}
};

keyValueMap enum_3537[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3538[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3539[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3553[] = {
    {1, 1, true},
    {2, 2, true},
    {3, 3, true},
    {4, 4, true},
    {5, 5, true},
    {6, 6, true},
    {7, 7, true}
};

keyValueMap enum_3554[] = {
    {1, 1, true},
    {2, 2, true},
    {3, 3, true},
    {4, 4, true},
    {5, 5, true},
    {6, 6, true}
};

keyValueMap enum_3556[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3557[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3558[] = {
    {0, 0, true},
    {1, 1, true},
    {2, 2, true}
};

keyValueMap enum_3559[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3560[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3563[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3568[] = {
    {0, 0, true},
    {1, 1, true},
    {2, 2, true}
};

keyValueMap enum_3571[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_3576[] = {
    {0, 0, true},
    {1, 1, true}
};

keyValueMap enum_6003[] = {
    {1, 1, true},
    {2, 2, true},
    {3, 3, true},
    {4, 4, true},
    {5, 5, true}
};

keyValueMap enum_6007[] = {
    {0, 2, true},
    {1, 1, true}
};

keyValueMap enum_6011[] = {
    {0, 2, true},
    {1, 1, true}
};

keyValueMap enum_6024[] = {
    {1, 1, true},
    {2, 2, true},
    {3, 3, true},
    {0, 0, true}
};

keyValueMap enum_6025[] = {
    {0, 1, true},
    {1, 2, true}
};

keyValueMap enum_6026[] = {
    {0, 1, true},
    {1, 2, true}
};

keyValueMap enum_6033[] = {
    {0, 1, true},
    {1, 2, true}
};

keyValueMap enum_6036[] = {
    {1, 1, true},
    {2, 2, true},
    {3, 3, true}
};

keyValueMap enum_6041[] = {
    {0, 2, true},
    {1, 1, true}
};

regEnumMap regEnumMapArray[] = {
{3505, sizeof(enum_3505) / sizeof(keyValueMap), (keyValueMap *)&enum_3505},
{3509, sizeof(enum_3509) / sizeof(keyValueMap), (keyValueMap *)&enum_3509},
{3510, sizeof(enum_3510) / sizeof(keyValueMap), (keyValueMap *)&enum_3510},
{3513, sizeof(enum_3513) / sizeof(keyValueMap), (keyValueMap *)&enum_3513},
{3515, sizeof(enum_3515) / sizeof(keyValueMap), (keyValueMap *)&enum_3515},
{3523, sizeof(enum_3523) / sizeof(keyValueMap), (keyValueMap *)&enum_3523},
{3528, sizeof(enum_3528) / sizeof(keyValueMap), (keyValueMap *)&enum_3528},
{3534, sizeof(enum_3534) / sizeof(keyValueMap), (keyValueMap *)&enum_3534},
{3535, sizeof(enum_3535) / sizeof(keyValueMap), (keyValueMap *)&enum_3535},
{3537, sizeof(enum_3537) / sizeof(keyValueMap), (keyValueMap *)&enum_3537},
{3538, sizeof(enum_3538) / sizeof(keyValueMap), (keyValueMap *)&enum_3538},
{3539, sizeof(enum_3539) / sizeof(keyValueMap), (keyValueMap *)&enum_3539},
{3553, sizeof(enum_3553) / sizeof(keyValueMap), (keyValueMap *)&enum_3553},
{3554, sizeof(enum_3554) / sizeof(keyValueMap), (keyValueMap *)&enum_3554},
{3556, sizeof(enum_3556) / sizeof(keyValueMap), (keyValueMap *)&enum_3556},
{3557, sizeof(enum_3557) / sizeof(keyValueMap), (keyValueMap *)&enum_3557},
{3558, sizeof(enum_3558) / sizeof(keyValueMap), (keyValueMap *)&enum_3558},
{3559, sizeof(enum_3559) / sizeof(keyValueMap), (keyValueMap *)&enum_3559},
{3560, sizeof(enum_3560) / sizeof(keyValueMap), (keyValueMap *)&enum_3560},
{3563, sizeof(enum_3563) / sizeof(keyValueMap), (keyValueMap *)&enum_3563},
{3568, sizeof(enum_3568) / sizeof(keyValueMap), (keyValueMap *)&enum_3568},
{3571, sizeof(enum_3571) / sizeof(keyValueMap), (keyValueMap *)&enum_3571},
{3576, sizeof(enum_3576) / sizeof(keyValueMap), (keyValueMap *)&enum_3576},
{6003, sizeof(enum_6003) / sizeof(keyValueMap), (keyValueMap *)&enum_6003},
{6007, sizeof(enum_6007) / sizeof(keyValueMap), (keyValueMap *)&enum_6007},
{6011, sizeof(enum_6011) / sizeof(keyValueMap), (keyValueMap *)&enum_6011},
{6024, sizeof(enum_6024) / sizeof(keyValueMap), (keyValueMap *)&enum_6024},
{6025, sizeof(enum_6025) / sizeof(keyValueMap), (keyValueMap *)&enum_6025},
{6026, sizeof(enum_6026) / sizeof(keyValueMap), (keyValueMap *)&enum_6026},
{6033, sizeof(enum_6033) / sizeof(keyValueMap), (keyValueMap *)&enum_6033},
{6036, sizeof(enum_6036) / sizeof(keyValueMap), (keyValueMap *)&enum_6036},
{6041, sizeof(enum_6041) / sizeof(keyValueMap), (keyValueMap *)&enum_6041}
};

bool regMap_isExist(int addr)
{
    int mapSize = 0;
    int i = 0;
    bool ret = false;

    mapSize = sizeof(regEnumMapArray) / sizeof(regEnumMap);
    for (i = 0; i < mapSize; i++) {
        if (regEnumMapArray[i].addr == addr) {
            ret = true;
            break;
        }
    }
    return ret;
}

bool regMap_search_byKey(int addr, int key, int *value)
{
    int mapSize = 0;
    int i = 0;
    int j = 0;
    bool ret = false;

    mapSize = sizeof(regEnumMapArray) / sizeof(regEnumMap);
    for (i = 0; i < mapSize; i++) {
        if (regEnumMapArray[i].addr != addr) {
            continue;
        }
        for (j = 0; j < regEnumMapArray[i].mum; j++) {
            if (regEnumMapArray[i].Map[j].key != key) {
                continue;
            }
#ifdef DEBUG
            printf("regMap by key:addr[%d] key[%d] ==> value[%d]\n", addr, key, regEnumMapArray[i].Map[j].value);
#endif
            *value = regEnumMapArray[i].Map[j].value;
            if (regEnumMapArray[i].Map[j].valid == true) {
                ret = true;
            } else {
                ret = false;
            }

            break;
        }
        break;
    }
    return ret;
}

bool regMap_search_byValue(int addr, int value, int *key)
{
    int mapSize = 0;
    int i = 0;
    int j = 0;
    bool ret = false;

    mapSize = sizeof(regEnumMapArray) / sizeof(regEnumMap);
    for (i = 0; i < mapSize; i++) {
        if (regEnumMapArray[i].addr != addr) {
            continue;
        }
        for (j = 0; j < regEnumMapArray[i].mum; j++) {
            if (regEnumMapArray[i].Map[j].value != value) {
                continue;
            }
#ifdef DEBUG
            printf("regMap by value:addr[%d] value[%d] ==> key[%d]\n", addr, value, regEnumMapArray[i].Map[j].key);
#endif
            *key = regEnumMapArray[i].Map[j].key;
            ret = true;
            break;
        }
        break;
    }
    return ret;
}

void reg3553_process(int value)
{
    switch(value) {
        case 1:
            enum_3554[0].valid = true;
            enum_3554[1].valid = false;
            enum_3554[2].valid = false;
            enum_3554[3].valid = false;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        case 2:
            enum_3554[0].valid = true;
            enum_3554[1].valid = true;
            enum_3554[2].valid = true;
            enum_3554[3].valid = true;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        case 3:
            enum_3554[0].valid = true;
            enum_3554[1].valid = true;
            enum_3554[2].valid = true;
            enum_3554[3].valid = true;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        case 4:
            enum_3554[0].valid = true;
            enum_3554[1].valid = false;
            enum_3554[2].valid = false;
            enum_3554[3].valid = false;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        case 5:
            enum_3554[0].valid = true;
            enum_3554[1].valid = true;
            enum_3554[2].valid = true;
            enum_3554[3].valid = true;
            enum_3554[4].valid = true;
            enum_3554[5].valid = true;
            break;
        case 6:
            enum_3554[0].valid = true;
            enum_3554[1].valid = true;
            enum_3554[2].valid = true;
            enum_3554[3].valid = false;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        case 7:
            enum_3554[0].valid = true;
            enum_3554[1].valid = false;
            enum_3554[2].valid = false;
            enum_3554[3].valid = false;
            enum_3554[4].valid = false;
            enum_3554[5].valid = false;
            break;
        default:
            enum_3554[0].valid = true;
            enum_3554[1].valid = true;
            enum_3554[2].valid = true;
            enum_3554[3].valid = true;
            enum_3554[4].valid = true;
            enum_3554[5].valid = true;
            break;
    };
}

void reg3513_process(int value)
{
    RegisterDesc *registerDesc = get_registerDesc(3514, REG_SEND);
    switch(value) {
        case 380:
            set_dataAttribute_range(registerDesc->dataPtr, 209.0, 231.0);
            break;
        case 400:
            set_dataAttribute_range(registerDesc->dataPtr, 219.0, 241.0);
            break;
        case 415:
            set_dataAttribute_range(registerDesc->dataPtr, 228.0, 252.0);
            break;
        default:
            set_dataAttribute_range(registerDesc->dataPtr, 209.0, 252.0);
            break;
    };
}